8.2: Menjadwalkan Alarm
Materi:
- Pengantar
- Tipe alarm
- Praktik terbaik alarm
- Menjadwalkan alarm
- Memeriksa alarm yang ada
- Membatalkan alarm
- Alarm yang terlihat pengguna ("jam alarm")
- Praktik terkait
- Ketahui selengkapnya
Anda sudah mengetahui cara menggunakan penerima siaran untuk membuat aplikasi merespons kejadian sistem bahkan bila aplikasi sedang tidak dijalankan. Dalam bab ini, Anda akan mempelajari cara menggunakan alarm untuk menjadwalkan tugas selama waktu tertentu, baik aplikasi dijalankan pada saat alarm disetel untuk aktif maupun tidak. Alarm bisa untuk sekali penggunaan atau berulang. Misalnya, Anda bisa menggunakan alarm berulang untuk menjadwalkan pengunduhan setiap hari pada waktu yang sama.
Untuk membuat alarm, gunakan kelas AlarmManager
. Alarm di Android memiliki karakteristik berikut:
- Alarm memungkinkan Anda mengirim maksud pada waktu atau interval yang disetel. Anda bisa menggunakan alarm bersama penerima siaran untuk memulai layanan dan menjalankan operasi lainnya.
- Alarm beroperasi di luar aplikasi, sehingga Anda bisa menggunakannya untuk memicu kejadian atau tindakan bahkan saat aplikasi sedang tidak dijalankan, dan bahkan jika perangkat nonaktif.
- Bila digunakan dengan benar, alarm bisa membantu Anda meminimalkan kebutuhan sumber daya aplikasi. Misalnya, Anda bisa menjadwalkan operasi tanpa mengandalkan timer atau terus menjalankan layanan latar belakang.
Bila tidak menggunakan alarm:
- Untuk kejadian pengaturan waktu seperti tick dan waktu tunggu, dan untuk operasi berwaktu yang dipastikan terjadi selama masa aplikasi Anda, gunakan kelas
Handler
bersamaTimer
danThread
. Pendekatan ini memberi Android kontrol yang lebih baik atas sumber daya sistem daripada jika Anda menggunakan alarm. - Untuk operasi sinkronisasi server, gunakan
SyncAdapter
bersama Google Cloud Messaging Service. - Untuk tugas yang bisa menunggu hingga kondisi memungkinkan, seperti bila perangkat terhubung ke WiFi dan sedang mengisi daya (misalnya, memperbarui informasi cuaca atau kabar berita), Anda mungkin tidak ingin menggunakan alarm. Untuk tugas ini di perangkat API 21+, pertimbangkan penggunaan
JobScheduler
, yang akan Anda pelajari di pelajaran mendatang.
Tipe alarm
Ada dua tipe alarm umum di Android: alarm waktu tempuh riil serta alarm jam real-time (RTC), dan keduanya menggunakan objek PendingIntent
.
Alarm waktu tempuh riil
Alarm waktu tempuh riil menggunakan waktu, dalam milidetik, sejak perangkat melakukan booting. Alarm waktu tempuh riil tidak terpengaruh oleh zona waktu, sehingga bekerja dengan baik untuk alarm berdasarkan waktu yang telah ditempuh. Misalnya, gunakan alarm waktu tempuh riil untuk alarm yang aktif setiap setengah jam.
Kelas AlarmManager menyediakan dua tipe alarm waktu tempuh riil:
ELAPSED_REALTIME
: Akan memicuPendingIntent
berdasarkan pada jumlah waktu sejak perangkat booting, namun tidak membangunkan perangkat. Waktu tempuh menyertakan waktu selama perangkat sedang tidur. Semua alarm berulang akan terpicu bila perangkat bangun pada waktu berikutnya.ELAPSED_REALTIME_WAKEUP
: Akan memicuPendingIntent
setelah jangka waktu yang ditetapkan berlalu sejak perangkat booting, yang membangunkan CPU perangkat jika layar mati. Gunakan alarm ini sebagai gantiELAPSED_REALTIME
jika aplikasi Anda memiliki dependensi waktu, misalnya jika memiliki jendela terbatas selama menjalankan operasi.
Alarm jam real-time (RTC)
Alarm jam real-time (RTC) adalah alarm berbasis jam yang menggunakan Coordinated Universal Time (UTC). Hanya pilih alarm RTC dalam tipe situasi ini:
- Anda perlu alarm yang dipicu pada waktu tertentu dalam sehari.
- Waktu alarm bergantung pada lokal saat ini.
Aplikasi dengan alarm berbasis jam mungkin tidak berfungsi dengan baik di seluruh lokal, karena mungkin akan terpicu pada waktu yang salah. Dan jika pengguna mengubah setelan waktu perangkat, maka hal itu bisa menyebabkan perilaku yang tidak diharapkan di aplikasi Anda.
Kelas AlarmManager
menyediakan dua tipe alarm RTC:
RTC
: Akan memicu maksud yang menunggu pada waktu yang ditetapkan, namun tidak membangunkan perangkat. Semua alarm berulang akan terpicu bila perangkat bangun pada waktu berikutnya.RTC_WAKEUP
: Akan memicu maksud yang menunggu pada waktu yang ditetapkan, yang membangunkan CPU perangkat jika layar mati.
Praktik terbaik alarm
Alarm memengaruhi cara aplikasi Anda menggunakan (atau menyalahgunakan) sumber daya sistem. Misalnya, bayangkan aplikasi populer yang menyinkronkan dengan server. Jika operasi sinkronisasi berdasarkan pada waktu jam dan setiap instance aplikasi menghubungkan ke server pada waktu yang sama, beban pada server bisa mengakibatkan waktu respons tertunda atau bahkan kondisi "denial of service".
Untuk menghindari masalah ini dan masalah lainya, ikuti praktik terbaik ini:
- Tambahkan keacakan (jitter) ke permintaan jaringan yang terpicu akibat alarm berulang. Inilah satu cara untuk melakukannya:
- Jadwalkan alarm pasti yang menjalankan suatu pekerjaan lokal. "Pekerjaan lokal" berarti sesuatu yang tidak menghubungi server melalui jaringan atau memerlukan data dari server.
- Jadwalkan alarm terpisah yang berisi permintaan jaringan, dan setel alarm ini agar terpicu setelah periode waktu acak. Biasanya alarm kedua ini disetel oleh komponen apa pun yang menerima
PendingIntent
dari alarm pertama. (Anda juga bisa menyetel alarm ini pada waktu yang sama seperti alarm pertama.)
- Pertahankan frekuensi alarm Anda tetap minimum.
- Jangan bangunkan perangkat jika tidak diperlukan.
- Gunakan pengaturan waktu yang paling tidak akurat untuk memungkinkan
AlarmManager
menjadi yang paling efisien. Misalnya, bila Anda menjadwalkan alarm berulang, gunakansetInexactRepeating()
sebagai gantisetRepeating()
. Untuk detailnya, lihat Menjadwalkan alarm berulang, di bawah ini. - Hindari mendasarkan alarm pada waktu jam dan gunakan
ELAPSED_REALTIME
untuk alarm berulang bila memungkinkan. Alarm berulang yang berdasarkan pada waktu pemicu akurat tidak akan menskalakan dengan baik.
Menjadwalkan alarm
Kelas AlarmManager
memberi Anda akses ke layanan alarm sistem Android. AlarmManager
memungkinkan Anda menyiarkan Intent
pada waktu yang dijadwalkan, atau setelah interval tertentu.
Untuk menjadwalkan alarm:
- Panggil
getSystemService(ALARM_SERVICE)
untuk mendapatkan instance kelasAlarmManager
. - Gunakan salah satu metode
set...()
yang tersedia diAlarmManager
(sebagaimana dijelaskan di bawah ini). Metode yang Anda gunakan bergantung pada apakah alarm telah menempuh waktu yang riil, atau RTC.
Semua metode AlarmManager.set...()
menyertakan dua argumen:
- Argumen
type
, yakni cara Anda menetapkan tipe alarm:ELAPSED_REALTIME
atauELAPSED_REALTIME_WAKEUP
, yang dijelaskan di Alarm waktu tempuh riil di atas.RTC
atauRTC_WAKEUP
, yang dijelaskan di Alarm jam real-time (RTC) di atas.
- Objek
PendingIntent
, yakni cara Anda menetapkan tugas yang akan dijalankan pada waktu yang diberikan.
Menjadwalkan alarm sekali-pakai
Untuk menjadwalkan satu alarm, gunakan salah satu metode berikut ini di instance AlarmManager
:
set()
: Untuk perangkat yang menjalankan API 19+, metode ini menjadwalkan satu alarm berwaktu tidak pasti, maksudnya, sistem akan menggeser alarm untuk meminimalkan membangunkan dan penggunaan baterai. Untuk perangkat yang menjalankan versi API lebih rendah, metode ini menjadwalkan alarm yang berwaktu pasti.setWindow()
: Untuk perangkat yang menjalankan API 19+, gunakan metode ini untuk menyetel jangka waktu untuk memicu alarm.setExact()
: Untuk perangkat yang menjalankan API 19+, metode ini memicu alarm pada waktu yang pasti. Gunakan metode ini hanya untuk alarm yang harus dipicu pada waktu yang pasti, misalnya jam alarm yang berdering pada waktu yang diminta. Alarm pasti akan mengurangi kemampuan OS untuk meminimalkan penggunaan baterai, jadi jangan menggunakannya jika tidak diperlukan.
Inilah contoh penggunaan set()
untuk menjadwalkan alarm sekali-pakai:
alarmMgr.set(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 1000*300,
alarmIntent);
Dalam contoh ini:
- Kelas
type
adalahELAPSED_REALTIME
, yang berarti bahwa ini adalah alarm waktu tempuh riil. Jika perangkat sedang tidak digunakan saat alarm dikirim, alarm tidak akan membangunkan perangkat. - Alarm dikirim 5 menit (300.000 milidetik) setelah metode dikembalikan.
alarmIntent
adalah siaranPendingIntent
berisi aksi yang akan dijalankan ketika alarm dikirim.Catatan: Untuk operasi pengaturan waktu seperti tick dan waktu tunggu, serta kejadian yang lebih dari sekali dalam satu menit, akan lebih mudah dan efisien menggunakan Penangan daripada alarm.
Istirahatkan dan Aplikasi Siaga
Perangkat API 23+ kadang-kadang masuk ke mode Istirahatkan atau Aplikasi Siaga untuk menghemat daya:
- Mode Istirahatkan dipicu bila pengguna meninggalkan perangkat yang stekernya tidak terhubung dan tidak bergerak selama periode waktu tertentu, dengan layar dimatikan. Selama "masa pemeliharaan" singkat, sistem akan keluar dari Istirahatkan untuk memungkinkan aplikasi menyelesaikan aktivitas yang ditangguhkan, termasuk memicu alarm standar, kemudian kembali ke Istirahatkan. Mode Istirahatkan berakhir bila pengguna kembali ke perangkat mereka.
- Mode Aplikasi Siaga dipicu pada aplikasi diam yang tidak digunakan baru-baru ini. Mode Aplikasi Siaga berakhir bila pengguna kembali ke aplikasi atau menghubungkan steker di perangkat.
Untuk menggunakan alarm dengan Istirahatkan dan Aplikasi Siaga:
- Jika Anda memerlukan alarm yang terpicu saat perangkat berada dalam mode Istrahatkan atau Aplikasi Siaga tanpa menunggu masa pemeliharaan, gunakan
setAndAllowWhileIdle()
untuk alarm tidak pasti dansetExactAndAllowWhileIdle()
untuk alarm pasti, atau setel alarm yang terlihat pengguna (API 21+). - Beberapa alarm bisa menunggu masa pemeliharaan, atau hingga perangkat keluar dari mode Istirahatkan atau Aplikasi Siaga. Untuk alarm ini, gunakan metode
set()
dansetExact()
standar untuk mengoptimalkan daya tahan baterai.
Menjadwalkan alarm berulang
Anda juga bisa menggunakan AlarmManager
untuk menjadwalkan alarm berulang, dengan menggunakan salah satu metode berikut:
setRepeating()
: Sebelum Android 4.4 (API Level 19), metode ini akan membuat alarm berulang dengan waktu yang pasti. Pada perangkat yang menjalankan API 19 dan yang lebih tinggi, perilakusetRepeating()
benar-benar sepertisetInexactRepeating()
.setInexactRepeating()
: Metode ini membuat alarm tidak pasti berulang yang memungkinkan batch. Bila Anda menggunakansetInexactRepeating()
, Android akan menyinkronkan alarm berulang untuk beberapa aplikasi dan memicunya pada waktu yang sama. Hal ini mengurangi jumlah total waktu yang digunakan sistem untuk membangunkan perangkat, sehingga mengurangi konsumsi daya baterai. Seperti pada API 19, semua alarm berulang adalah alarm tidak pasti.
Untuk mengurangi kemungkinan konsumsi daya baterai:
- Jadwalkan alarm berulang menjadi sejarang mungkin.
- Gunakan pengaturan waktu tidak pasti, yang memungkinkan sistem untuk menyatukan alarm dari aplikasi yang berbeda.
Catatan: meskipun setInexactRepeating()
merupakan perbaikan atas setRepeating()
, tetap saja bisa membebani server jika setiap instance aplikasi menghubungkan ke server pada waktu yang kurang lebih sama. Oleh karena itu, untuk permintaan jaringan, tambahkan beberapa keacakan pada alarm Anda, seperti yang dijelaskan dalam Praktik terbaik alarm.
Jika Anda benar-benar memerlukan alarm pasti yang berulang pada API 19+, setel alarm sekali-pakai dengan setExact()
dan setel alarm berikutnya setelah alarm itu dipicu. Alarm kedua ini disetel oleh komponen apa pun yang menerima PendingIntent
—biasanya layanan atau penerima siaran.
Inilah contoh penggunaan setInexactRepeating()
untuk menjadwalkan alarm berulang:
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(),
AlarmManager.INTERVAL_FIFTEEN_MINUTES,
alarmIntent);
Dalam contoh ini:
- Dalam hal ini,
type
adalahRTC_WAKEUP
, berarti alarm ini adalah alarm berbasis jam yang membangunkan perangkat bila alarm telah dikirim. - Kekerapan alarm pertama dikirim segera, karena
calendar.getTimeInMillis()
mengembalikan waktu saat ini sebagai UTC milidetik. Setelah kekerapan pertama, alarm dikirim kurang lebih setiap 15 menit.
Jika metodenya adalah
setRepeating()
sebagai gantisetInexactRepeating()
, dan jika perangkat menjalankan versi API yang lebih rendah dari 19, alarm pasti dikirim setiap 15 menit.Nilai-nilai yang memungkinkan untuk argumen ini adalah
INTERVAL_DAY
,INTERVAL_FIFTEEN_MINUTES
,INTERVAL_HALF_DAY
,INTERVAL_HALF_HOUR
,INTERVAL_HOUR
.alarmIntent
adalahPendingIntent
yang berisi aksi untuk dijalankan bila alarm telah dikirim. Maksud ini biasanya berasal dariIntentSender.getBroadcast()
.
Memeriksa alarm yang ada
Sering kali ada gunanya memeriksa apakah alarm sudah disetel. Misalnya, Anda mungkin ingin menonaktifkan kemampuan untuk menyetel alarm lain jika sudah ada alarm yang disetel.
Untuk memeriksa alarm yang ada:
Buat
PendingIntent
yang berisiIntent
serupa yang digunakan untuk menyetel alarm, namun kali ini menggunakan flagFLAG_NO_CREATE
.Dengan
FLAG_NO_CREATE
,PendingIntent
hanya dibuat jika sudah ada yang berisiIntent
yang sama. Jika tidak maka permintaan akan mengembalikannol
.- Periksa apakah
PendingIntent
adalahnull
:- Jika ini
null
, berarti alarm belum disetel. - Jika bukan
null
, makaPendingIntent
sudah ada, berarti alarm telah disetel.
- Jika ini
Misalnya, kode berikut akan mengembalikan true
jika alarm yang dimuat dalam alarmIntent
sudah ada:
boolean alarmExists =
(PendingIntent.getBroadcast(this, 0,
alarmIntent,
PendingIntent.FLAG_NO_CREATE) != null);
Membatalkan alarm
Untuk membatalkan alarm, gunakan cancel()
dan teruskan di PendingIntent
. Misalnya:
alarmManager.cancel(alarmIntent);
Alarm yang terlihat pengguna ("jam alarm")
Untuk perangkat API 21+, Anda bisa menyetel jam alarm yang terlihat pengguna dengan memanggil setAlarmClock()
. Aplikasi bisa mengambil jam alarm yang terlihat pengguna berikutnya yang disetel agar terpicu dengan memanggil getNextAlarmClock()
.
Jam alarm yang disetel dengan setAlarmClock()
akan berfungsi, bahkan bila perangkat atau aplikasi dalam keadaan diam (serupa dengan setExactAndAllowWhileIdle()
), yang membuat Anda sedekat mungkin dengan panggilan membangunkan yang pasti.
Praktik terkait
Latihan terkait dan dokumentasi praktik ada di Dasar-Dasar Developer Android: Praktik.